/**
 * 内置的加解密工具方法
 *  作用：
 *    1. 对关键的信息前后台传输进行加解密处理，提高信息安全性（比如账户名称和密码）
 *    
 *  注意：
 *    1. 秘钥和秘钥偏移量加解密需要一致,其实这个是与服务端约定好就行
 *    2. 秘钥和秘钥偏移量是十六位的数字和字母组合而成
 */

const CryptoJSAes = require('crypto-js/aes'); //引用AES源码js
const CryptoJSEncBase64 = require('crypto-js/enc-base64'); //引用AES源码js
const CryptoJSEncUtf8 = require('crypto-js/enc-utf8'); //引用AES源码js
const CryptoJSCore = require('crypto-js/core'); //引用AES源码js
const CryptoJSPadPkcs7 = require('crypto-js/pad-pkcs7'); //引用AES源码js

import config from 'common/config';

/**
 * 根据key和iv生成相对应的值
 *
 * @param {*} secretKey  密钥
 * @param {*} secretIv   密钥偏移量
 * @param {*} type       加密类型
 */
const generateSecretKeyAndIv = (secretKey, secretIv, type) => {
  type = type || 'aes';
  //十六位十六进制数作为密钥
  secretKey = secretKey || config.secret.key;
  //十六位十六进制数作为密钥偏移量
  secretIv = secretIv || config.secret.iv;
  if (type === 'aes') {
    return {
      key: CryptoJSEncUtf8.parse(secretKey),
      iv: CryptoJSEncUtf8.parse(secretIv),
    };
  }
};
// 生成公共的秘钥和偏移量
const { key : globalKey, iv : globalIv } = generateSecretKeyAndIv(config.secret.key, config.secret.iv, 'aes');


/**
 * AES 加密方法
 * @param {*} word  加密的值
 * @param {*} key   秘钥
 * @param {*} iv    秘钥偏移量
 * 
 * import { aesDecrypt } from "utils/secret.js"
 * 
 *  // 使用内置的秘钥和秘钥偏移量
 *  const value = aesEncrypt('admin')   // "F6889AA527EA40FB0A2AECC5A28A694E"
 */
export const aesEncrypt = (word, key, iv) => {
  let srcs = CryptoJSEncUtf8.parse(word);
  // 加密后的秘钥和偏移量
  let generateKey = globalKey,
    generateIv = globalIv;
  // 如果自定义了key 或者 iv 那么就生成相对应的值
  if (key || iv) {
    let generate = generateSecretKeyAndIv(key || config.secret.key, iv || config.secret.iv, 'aes');
    generateKey = generate.key;
    generateIv = generate.iv;
  }
  let encrypted = CryptoJSAes.encrypt(srcs, generateKey, {
    iv: generateIv,
    mode: CryptoJSCore.mode.CBC,
    padding: CryptoJSPadPkcs7,
  });
  return encrypted.ciphertext.toString().toUpperCase();
};


/**
 * AES 解密方法
 * @param {*} word  加密的值
 * @param {*} key   秘钥
 * @param {*} iv    秘钥偏移量
 * 
 * @example
 * 
 *  import { aesDecrypt } from "utils/secret.js"
 * 
 *  // 使用内置的秘钥和秘钥偏移量
 *  const value = aesDecrypt('F6889AA527EA40FB0A2AECC5A28A694E')  //admin
 */
export const aesDecrypt = (word, key, iv) => {
  let encryptedHexStr = CryptoJSEnc.Hex.parse(word);
  let srcs = CryptoJSEncBase64.stringify(encryptedHexStr);
  // 默认key和iv都是使用通用生成的
  let generateKey = globalKey,
    generateIv = globalIv;
  // 如果自定义了key 或者 iv 那么就生成相对应的值
  if (key || iv) {
    let generate = generateSecretKeyAndIv(key || config.secret.key, iv || config.secret.iv, 'aes');
    generateKey = generate.key;
    generateIv = generate.iv;
  }
  let decrypt = CryptoJSAes.decrypt(srcs, generateKey, {
    iv: generateIv,
    mode: CryptoJSCore.mode.CBC,
    padding: CryptoJSPadPkcs7,
  });
  let decryptedStr = decrypt.toString(CryptoJSEncUtf8);
  return decryptedStr.toString();
};
